home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ABUSESRC.ZIP / AbuseSrc / abuse / net / abuse_ndrv.c next >
C/C++ Source or Header  |  1995-09-23  |  31KB  |  1,165 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <fcntl.h>
  4. #include <unistd.h>
  5. #include <sys/ioctl.h>
  6. #include <sys/stat.h>
  7. #include <sys/types.h>
  8. #include <sys/time.h>
  9. #include <string.h>
  10. #include <signal.h>
  11. #include <netinet/in.h>
  12. #include <sys/socket.h>
  13.  
  14.  
  15.  
  16. #include <sys/types.h>
  17. #include <sys/ipc.h>
  18. #include <sys/shm.h>
  19.  
  20.  
  21.  
  22.  
  23. #include <bstring.h>
  24.  
  25. #include <netdb.h>
  26.  
  27.  
  28. #include "netface.hpp"      // net interface structures to the engine will use
  29.  
  30. // these are the names of the fifos to create in tmp
  31. // that communitcate with the engine
  32.  
  33. #ifdef __sgi
  34. #define BIGUNS             // big endian word ordering
  35. #endif
  36.  
  37.  
  38. // these macros swap the "endians" of a word to intel form... this should be done for anything sent
  39. // across the net as the other computer might have a different endianess
  40.  
  41. #ifdef BIGUNS
  42. #define swap_short(x) (((((unsigned short) (x)))<<8)|((((unsigned short) (x)))>>8))
  43. #define swap_long(x) \
  44.    ((( ((unsigned long)(x)) )>>24)|((( ((unsigned long)(x)) )&0x00ff0000)>>8)| \
  45.    ((( ((unsigned long)(x)) )&0x0000ff00)<<8)|(( ((unsigned long)(x)) )<<24))
  46. #else
  47. #define swap_short(x) (x)
  48. #define swap_long(x) (x)
  49.  
  50. #endif
  51.  
  52.  
  53. #define DIN_NAME "/tmp/.abuse_ndrv_in"
  54. #define DOUT_NAME "/tmp/.abuse_ndrv_out"
  55.  
  56.  
  57. // the lock files is used in case a previous net driver is
  58. // already running
  59.  
  60. #define DLOCK_NAME "/tmp/.abuse_ndrv_lock"
  61.  
  62.  
  63. #define MAX_CLIENTS 32  // change this if you need more
  64. #define MAX_JOINERS 32  // maximum clients that can join at the same time
  65.  
  66. #define DEFAULT_COMM_PORT 20202
  67. #define DEFAULT_GAME_PORT 20203
  68.  
  69. #define uchar unsigned char
  70.  
  71. void net_watch();
  72. void setup_ports(int comm_port, int game_port);
  73.  
  74. int no_security=0;
  75. int driver_out_fd,driver_in_fd;
  76. int shm_seg_id=-1;
  77. void *shm_addr=(void *)-1;  // shmat returns -1 on failure
  78. base_memory_struct *base;   // points to shm_addr
  79. int comm_fd=-1,             // listening socket for commincation port
  80.     game_fd=-1;
  81. char *active_server=NULL;   // if -net option, fetch all files from "active server"
  82. int stand_alone=0;          // if we are running this stand-alone (not interfacing with the engine)
  83.  
  84. fd_set master_set;
  85. fd_set master_write_set;    // set a socket here if you detect a write_full
  86.  
  87. client_struct *client_array;  // points to an array of possible clients in shared memory
  88. join_struct *join_array;      // points to an array of possible joining clients in shared memory
  89. char default_fs_name[256];    // default file server name (set with parm -fs)
  90.  
  91.  
  92. void clean_up()      // on exit unattach all shared memory links
  93. {  
  94.   fprintf(stderr,"clean up......\n");
  95.   if (shm_seg_id!=-1)
  96.     shmctl(shm_seg_id,IPC_RMID,NULL);
  97.  
  98.   if (shm_addr!=(void *)-1) 
  99.   {
  100.     shmdt((char *)shm_addr);
  101.     shm_addr=(void *)-1;
  102.   }
  103.  
  104.   unlink(DIN_NAME);
  105.   unlink(DOUT_NAME);
  106.   unlink(DLOCK_NAME);
  107. }
  108.  
  109. #ifdef __sgi
  110. void die(...)
  111. #else
  112. void die(int why)
  113. #endif
  114.   fprintf(stderr,"dieing\n");
  115.   clean_up();
  116.   exit(0);
  117. }
  118.  
  119. void mdie(char *reason)
  120. {
  121.   fprintf(stderr,"net driver : %s\n",reason);
  122.   die(0);
  123. }
  124.  
  125. void comm_failed()  // general communication failure with engine
  126. {
  127.   fprintf(stderr,"net driver : Error occured while trying to communicate with the engine\n");
  128.   clean_up();
  129.   exit(0);
  130. }
  131.  
  132.  
  133. main(int argc, char **argv)
  134. {
  135.   int i;
  136.   strcpy(default_fs_name,"");          // initially no default file server
  137.  
  138.   for (i=1;i<argc;i++)
  139.     if (!strcmp(argv[i],"-bastard"))   // this bypasses filename security features
  140.     {
  141.       fprintf(stderr,"Warning : Security measures bypassed (-bastard)\n");
  142.       no_security=1;
  143.     }
  144.  
  145.  
  146.   // make sure this program was run by the abuse engine
  147.   if (argc<2 || strcmp(argv[1],"runme"))   
  148.   { 
  149.     stand_alone=1;
  150.     fprintf(stderr,"%s is normally run by abuse, running stand-alone file server\n"
  151.                "Server will be killed by running abuse\n",argv[0]);
  152.   }
  153.  
  154.  
  155.   // see if we are already running, if so kill old driver
  156.   FILE *fp=fopen(DLOCK_NAME,"rb");
  157.   if (fp)
  158.   {
  159.     int pid;
  160.     if (fscanf(fp,"%d",&pid)==1)
  161.     {
  162.       struct stat st;
  163.       char proc_path[50];
  164.       sprintf(proc_path,"/proc/%d",pid);
  165.       if (!stat(proc_path,&st))
  166.       {
  167.     fprintf(stderr,"net driver : warning, %s already running, attempting to kill...\n",argv[0]);
  168.     if (kill(pid,SIGKILL))
  169.     {
  170.       fprintf(stderr,"net driver : unable to kill process %d, cannot run net-abuse\n",pid);
  171.       fclose(fp);
  172.       return 0;
  173.     }
  174.     fprintf(stderr,"killed process %d\n",pid);
  175.       }
  176.     }
  177.     fclose(fp);
  178.     unlink(DLOCK_NAME);    
  179.   }
  180.  
  181.  
  182.   unlink(DIN_NAME);    // remove any previous files if they exsists
  183.   unlink(DOUT_NAME);
  184.  
  185.  
  186.   if (!stand_alone)
  187.   {
  188.     if (mkfifo(DIN_NAME,S_IRWXU | S_IRWXG | S_IRWXO))
  189.     { perror("Net driver : unable to make fifo in /tmp");
  190.       return 0;
  191.     }
  192.     chmod(DIN_NAME,S_IRWXU | S_IRWXG | S_IRWXO);   // just to be sure umask doesn't screw us
  193.  
  194.     if (mkfifo(DOUT_NAME,S_IRWXU | S_IRWXG | S_IRWXO))
  195.     { perror("Net driver : unable to make fifo in /tmp");
  196.       return 0;
  197.     }
  198.     chmod(DOUT_NAME,S_IRWXU | S_IRWXG | S_IRWXO);
  199.  
  200.     int i,no_fork=0;
  201.     for (i=1;i<argc;i++)
  202.     if (!strcmp(argv[i],"-no_fork"))    // use this to debug easier
  203.       no_fork=1;
  204.     
  205.     if (!no_fork)      // use this for debugging
  206.     {
  207.       int child_pid=fork();
  208.       if (child_pid)
  209.       {
  210.     FILE *fp=fopen(DLOCK_NAME,"wb");
  211.     if (!fp)
  212.     { 
  213.       fprintf(stderr,"Unable to open %s for writing, killing child\n",DLOCK_NAME);
  214.       kill(child_pid,SIGKILL);
  215.       return 0;
  216.     }
  217.     fprintf(fp,"%d\n",child_pid);
  218.     fclose(fp);
  219.     printf("%d\n",child_pid);         // tell parent the sound driver's process number
  220.     return 0;                         // exit, child will continue
  221.       }
  222.     }  
  223.  
  224.     driver_out_fd=open(DOUT_NAME,O_RDWR);  // open the pipe
  225.     if (driver_out_fd<0)
  226.     { perror(DOUT_NAME); 
  227.       exit(1);
  228.     }
  229.  
  230.     driver_in_fd=open(DIN_NAME,O_RDWR);
  231.     if (driver_in_fd<0)
  232.     { perror(DIN_NAME); 
  233.       exit(1);
  234.     }
  235.   } else driver_in_fd=driver_out_fd=-1;
  236.  
  237.  
  238.  
  239.   int catch_sigs[]={SIGHUP,SIGINT,SIGQUIT,SIGILL,SIGABRT,
  240.           SIGIOT,SIGFPE,SIGKILL,SIGUSR1,SIGSEGV,
  241.           SIGUSR2,SIGPIPE,SIGTERM,SIGCHLD,
  242.           SIGCONT,SIGSTOP,SIGTSTP,SIGTTIN,SIGTTOU,-1};
  243.  
  244.   for (i=0;catch_sigs[i]!=-1;i++)     // catch all signals in case we get
  245.     signal(catch_sigs[i],die);            // interrupted before we remove shmid
  246.  
  247.  
  248.   int alloc_size=sizeof(client_struct)*MAX_CLIENTS+
  249.                  sizeof(join_struct)*MAX_JOINERS+
  250.                  sizeof(base_memory_struct);
  251.  
  252.   shm_seg_id=shmget(IPC_PRIVATE,alloc_size,IPC_CREAT | 0777);
  253.   if (shm_seg_id==-1)
  254.     mdie("Unable to allocate shared memory");
  255.  
  256.  
  257.   shm_addr=shmat(shm_seg_id,NULL,0);  // attach as read/write
  258.   if (shm_addr==(void *)-1) 
  259.     mdie("could not attach shm seg");
  260.  
  261.   base=(base_memory_struct *)shm_addr;
  262.   base->active_clients=NULL;
  263.   base->join_list=NULL;
  264.   base->mem_lock=0;
  265.   base->calc_crcs=0;
  266.  
  267.   if (!stand_alone)
  268.   {
  269.     // see if we can attach this memory with the abuse engine
  270.     if (write(driver_out_fd,&shm_seg_id,sizeof(shm_seg_id))!=sizeof(shm_seg_id))
  271.       comm_failed();
  272.  
  273.     // wait for engine to ack it has attached
  274.     uchar ack=0;
  275.     if (read(driver_in_fd,&ack,1)!=1 || ack!=1)
  276.       comm_failed();
  277.   }
  278.  
  279.   
  280.   if (shmctl(shm_seg_id,IPC_RMID,NULL))  // remove the shm id
  281.     mdie("could not remove shm id");
  282.  
  283.   shm_seg_id=-1;                      // mark as not allocated
  284.  
  285.  
  286.   int comm_port=DEFAULT_COMM_PORT;
  287.   int game_port=-1;
  288.   for (i=1;i<argc-1;i++)
  289.     if (!strcmp(argv[i],"-port"))
  290.     {
  291.       comm_port=atoi(argv[i+1]);
  292.       if (game_port==-1)
  293.         game_port=comm_port+1;
  294.     }
  295.     else if (!strcmp(argv[i],"-game_port"))
  296.       game_port=atoi(argv[i+1]);
  297.     else if (!strcmp(argv[i],"-net"))
  298.       active_server=argv[i+1];
  299.  
  300.   if (game_port==-1) game_port=DEFAULT_GAME_PORT;
  301.  
  302.   setup_ports(comm_port,game_port);
  303.  
  304.  
  305.   net_watch();                        // now go into infinite block/read/process cycle
  306.  
  307.   return 0;
  308. }
  309.  
  310.  
  311. void secure_filename(char *filename, char *mode)
  312. {
  313.   if (!no_security)
  314.   {    
  315.     if (filename[0]=='/') { filename[0]=0; return ; }
  316.     int level=0;
  317.     char *f=filename;
  318.     while (*f)
  319.     {
  320.       if (*f=='/') { f++; level++; }
  321.       else if (*f=='.' && f[1]=='.')
  322.       {
  323.     if (f[3]=='.') while (*f!='.') f++;
  324.     else
  325.     {
  326.       f+=2;
  327.       level--;
  328.     }
  329.       } else f++; 
  330.       
  331.     }
  332.     if (level<0)
  333.       filename[0]=0;
  334.   }
  335. }
  336.  
  337. int total_clients=0;
  338. int total_joiners=0;
  339.  
  340. class client
  341. {
  342. public :
  343.   int socket_fd;
  344.   int client_id;       // index into client_struct
  345.   int has_joined;
  346.   client *next;
  347.   client(int sock, int id, client *Next) { socket_fd=sock; client_id=id; next=Next; has_joined=0; }
  348. } *first_client=NULL;
  349.  
  350.  
  351. class nfs_client    // this is a client only read's a file
  352. {
  353.   public :
  354.   int socket_fd;
  355.   int file_fd;
  356.  
  357.   long size_to_read;  
  358.   long size;
  359.   nfs_client *next;
  360.   nfs_client(int Socket_fd, int File_fd, nfs_client *Next) 
  361.   { 
  362.     socket_fd=Socket_fd; 
  363.     file_fd=File_fd; 
  364.     next=Next; 
  365.     size_to_read=0;
  366.     FD_SET(socket_fd,&master_set);
  367.   }  
  368.   int send_read();             // flushes as much of size_to_read as possible
  369.   ~nfs_client() 
  370.   { 
  371.     if (socket_fd>=0) 
  372.       close(socket_fd); 
  373.     if (file_fd>=0)
  374.       close(file_fd);
  375.     FD_CLR(socket_fd,&master_set);
  376.   }
  377. } *first_nfs_client=NULL;
  378.  
  379.  
  380. void setup_ports(int comm_port, int game_port)
  381. {
  382.   // the comminication socket is a STREAM
  383.   comm_fd=socket(AF_INET,SOCK_STREAM,0);
  384.   if (comm_fd==-1)
  385.     mdie("net driver : could not create a socket.  (too many open files?)");
  386.  
  387.  
  388.   sockaddr_in host;
  389.   memset( (char*) &host,0, sizeof(host));
  390.   host.sin_family = AF_INET;
  391.   host.sin_port = htons(comm_port);
  392.   host.sin_addr.s_addr = htonl (INADDR_ANY);
  393.   if (bind(comm_fd, (struct sockaddr *) &host, sizeof(sockaddr_in))==-1)
  394.   {
  395.     fprintf(stderr,"net driver : could not bind socket to port %d",comm_port);
  396.     die(0);
  397.   }
  398.  
  399.   if (listen(comm_fd,5)==-1)
  400.   {
  401.     fprintf(stderr,"net driver : could not listen to socket on port %d\n",comm_port);    
  402.     die(0);
  403.   }
  404.  
  405.  
  406.   game_fd=socket(AF_INET,SOCK_DGRAM,0);
  407.   if (game_fd==-1)
  408.     mdie("net driver : could not create a socket.  (too many open files?)");
  409.  
  410.   memset( (char*) &host,0, sizeof(host));
  411.   host.sin_family = AF_INET;
  412.   host.sin_port = htons(game_port);
  413.   host.sin_addr.s_addr = htonl (INADDR_ANY);
  414.   if (bind(game_fd, (struct sockaddr *) &host, sizeof(sockaddr_in))==-1)
  415.   {
  416.     fprintf(stderr,"net driver : could not bind socket to port %d\n",game_port);
  417.     die(0);
  418.   }
  419. }
  420.  
  421.  
  422. void delete_client(client *c)
  423. {
  424.   FD_CLR(c->socket_fd,&master_set);   // don't listen to this client anymore
  425.  
  426.   client_array[c->client_id].input_state=WAIT_DELETE;  // inform server to delete this client
  427. }
  428.  
  429.  
  430. int aquire_mem_lock()
  431. {
  432.   if (base->mem_lock==0 || base->mem_lock==1)
  433.   {
  434.     base->mem_lock=1;
  435.     if (base->mem_lock==1)
  436.       return 1;
  437.   }
  438.   sleep(0);   // probably just gonna loop until we get the lock so halt for next preocess
  439.   return 0;
  440. }
  441.  
  442. int local_address(char *server_name)    // returns 1 if server name is ourself
  443. {
  444.   struct hostent *hn=gethostbyname(server_name);    // first check to see if this address is 127.0.0.1
  445.   if (!hn) return 0;                                // if bad server_name, return false
  446.   char **ip_address=hn->h_addr_list;
  447.   while (*ip_address) 
  448.   {
  449.     char *a=*ip_address;
  450.     if (a[0]==127 && a[1]==0 && a[2]==0 && a[3]==1)
  451.       return 1;
  452.     ip_address++;
  453.   }
  454.   
  455.   char my_name[100];                              // now check to see if this address is 'hostname'
  456.   gethostname(my_name,100);
  457.   struct hostent *l_hn=gethostbyname(my_name);  
  458.   char **l_ip_address=l_hn->h_addr_list;
  459.  
  460.   while (*l_ip_address)  // local ip_address
  461.   {
  462.     char *a=*l_ip_address;         // scan through all local ip's
  463.     ip_address=hn->h_addr_list;
  464.     while (*ip_address)            // scan through all ip's for server_name
  465.     {
  466.       char *b=*ip_address;
  467.       if (a[0]==b[0] && a[1]==b[1] && a[2]==b[2] && a[3]==b[3])    // check for match
  468.         return 1;
  469.       ip_address++;
  470.     }
  471.     l_ip_address++;
  472.   }
  473.  
  474.   return 0;       // didn't match localhost nor hostname, must be somewhere else
  475. }
  476.  
  477. int nfs_client::send_read()   // return 0 if failure on socket, not failure to read
  478. {
  479.   if (file_fd>=0 && socket_fd>=0)
  480.   {
  481.     // first make sure the socket isn't 'full'
  482.  
  483.     struct timeval tv={0,0};     // don't wait
  484.     fd_set write_check;  
  485.     FD_ZERO(&write_check);  
  486.     FD_SET(socket_fd,&write_check);     
  487.     select(FD_SETSIZE,NULL,&write_check,NULL,&tv);
  488.  
  489.     if (FD_ISSET(socket_fd,&write_check))            // ready to write?
  490.     {
  491.       char buf[READ_PACKET_SIZE];   
  492.       short read_total;
  493.       short actual;
  494.  
  495.       do
  496.       {      
  497.     read_total=size_to_read>(READ_PACKET_SIZE-2) ? (READ_PACKET_SIZE-2) : size_to_read;
  498.     actual=read(file_fd,buf,read_total);
  499.     actual=swap_short(actual);
  500.     if (write(socket_fd,&actual,sizeof(actual))!=sizeof(actual))
  501.     {
  502.       fprintf(stderr,"write failed\n");
  503.       return 0;
  504.     }
  505.     actual=swap_short(actual);
  506.  
  507.     int write_amount=write(socket_fd,buf,actual);
  508.     if (write_amount!=actual) 
  509.     {
  510.       fprintf(stderr,"write failed\n");
  511.       return 0;
  512.     }
  513.  
  514.     size_to_read-=actual;
  515.  
  516.     FD_ZERO(&write_check);  
  517.     FD_SET(socket_fd,&write_check);     
  518.     select(FD_SETSIZE,NULL,&write_check,NULL,&tv);
  519.  
  520.     if (!FD_ISSET(socket_fd,&write_check))
  521.     {
  522.       FD_SET(socket_fd,&master_write_set);      // socket is full, wait for it empty
  523.       FD_CLR(socket_fd,&master_set);            // don't check for reading or process commands till read is done
  524.       return 1;    // not ok to write anymore, try again latter
  525.     }
  526.  
  527.       } while (size_to_read && actual==read_total);
  528.       size_to_read=0;
  529.       FD_CLR(socket_fd,&master_write_set);       // don't check this socket for write ok
  530.       FD_SET(socket_fd,&master_set);             // check it for reading
  531.       return 1;
  532.     } else 
  533.     {
  534.       FD_SET(socket_fd,&master_write_set);      // socket is full, wait for it empty
  535.       FD_CLR(socket_fd,&master_set);            // don't check for reading or process commands till read is done
  536.       return 1;
  537.     }
  538.   }
  539.   return 0;
  540. }
  541.  
  542. class remote_file
  543. {
  544.  
  545.   public :
  546.   int socket_fd;
  547.   void r_close(char *reason)
  548.   { 
  549.     if (reason)
  550.        fprintf(stderr,"remote_file : %s\n",reason);
  551.     if (socket_fd>=0) 
  552.     {
  553.       uchar cmd=NFCMD_CLOSE;
  554.       write(socket_fd,&cmd,1);
  555.       close(socket_fd); 
  556.     }
  557.     socket_fd=-1; 
  558.   }
  559.  
  560.   long size;   // server tells us the size of the file when we open it
  561.   remote_file *next; 
  562.   remote_file(char *server, int port, char *filename, char *mode, remote_file *Next);
  563.  
  564.   int unbuffered_read(int out_fd, size_t count);
  565.   int unbuffered_write(void *buf, size_t count) { return 0; } // not supported
  566.   int unbuffered_tell();
  567.   int unbuffered_seek(long offset);
  568.   int file_size() { return size; }
  569.   int open_failure() { return socket_fd<0; }
  570.   ~remote_file() { r_close(NULL); }
  571.   int fd() { return socket_fd; }
  572. } ;
  573.  
  574. remote_file *remote_file_list;
  575.  
  576. remote_file::remote_file(char *server, int port, char *filename, char *mode, remote_file *Next)
  577. {
  578.   next=Next;
  579.   socket_fd=socket(AF_INET,SOCK_STREAM,0);
  580.   if (socket_fd<0) 
  581.   {
  582.     fprintf(stderr,"unable to open socket\n");
  583.     return ;
  584.   }
  585.  
  586.   hostent *hp=gethostbyname(server);
  587.   if (!hp)
  588.   { 
  589.     fprintf(stderr,"unable to locate server named '%s'\n",server);
  590.     close(socket_fd); socket_fd=-1; return ; 
  591.   }
  592.   
  593.  
  594.   sockaddr_in host;
  595.   memset( (char*) &host,0, sizeof(host));
  596.   host.sin_family = AF_INET;
  597.   host.sin_port = htons(port);
  598.   host.sin_addr.s_addr = htonl (INADDR_ANY);
  599.   memcpy(&host.sin_addr,hp->h_addr,hp->h_length);
  600.     
  601.   if (connect(socket_fd, (struct sockaddr *) &host, sizeof(host))==-1)
  602.   { 
  603.     fprintf(stderr,"unable to connect\n");
  604.     close(socket_fd);
  605.     socket_fd=-1;
  606.     return ;
  607.   }
  608.  
  609.   uchar sizes[3]={CLIENT_NFS,strlen(filename)+1,strlen(mode)+1};
  610.   if (write(socket_fd,sizes,3)!=3) { r_close("could not send open info"); return ; }
  611.   if (write(socket_fd,filename,sizes[1])!=sizes[1]) { r_close("could not send filename"); return ; }
  612.   if (write(socket_fd,mode,sizes[2])!=sizes[2]) { r_close("could not send mode"); return ; }
  613.  
  614.   long remote_file_fd;
  615.   if (read(socket_fd,&remote_file_fd,sizeof(remote_file_fd))!=sizeof(remote_file_fd)) 
  616.   { r_close("could not read remote fd"); return ; }   
  617.   remote_file_fd=swap_long(remote_file_fd);
  618.   if (remote_file_fd<0) { r_close("remote fd is bad"); return ; }
  619.  
  620.   if (read(socket_fd,&size,sizeof(size))!=sizeof(size)) { r_close("could not read remote filesize"); return ; } 
  621.   size=swap_long(size);
  622. }
  623.  
  624. int remote_file::unbuffered_read(int out_fd, size_t count)
  625. {
  626.   if (socket_fd>=0 && count)
  627.   {
  628.     uchar cmd=NFCMD_READ;
  629.     if (write(socket_fd,&cmd,sizeof(cmd))!=sizeof(cmd)) { r_close("read : could not send command"); return 0; }
  630.  
  631.     long rsize=swap_long(count);
  632.     if (write(socket_fd,&rsize,sizeof(rsize))!=sizeof(rsize)) { r_close("read : could not send size"); return 0; }
  633.  
  634.     long total_read=0,total;
  635.     char buf[READ_PACKET_SIZE];
  636.     ushort size;
  637.  
  638.     ushort packet_size;    
  639.     do
  640.     {
  641.       if (read(socket_fd,&packet_size,sizeof(packet_size))!=sizeof(packet_size)) 
  642.       {
  643.     fprintf(stderr,"could not read packet size\n");
  644.     return 0;
  645.       }
  646.       packet_size=swap_short(packet_size);
  647.  
  648.       ushort size_read=read(socket_fd,buf+2,packet_size);   
  649.  
  650.       if (size_read!=packet_size) 
  651.       { 
  652.     if (read(socket_fd,buf+2+size_read,packet_size-size_read)!=packet_size-size_read)
  653.     {
  654.       fprintf(stderr,"incomplete packet\n"); 
  655.       return 0; 
  656.     }
  657.       }
  658.  
  659.       *((short *)buf)=packet_size;
  660.       if (write(out_fd,buf,packet_size+2)!=packet_size+2) comm_failed();
  661.  
  662.       total_read+=packet_size;
  663.       count-=packet_size;
  664.     } while (packet_size==READ_PACKET_SIZE-2 && count);     
  665.     return total_read;
  666.   }
  667.   return 0;
  668. }
  669.  
  670. int remote_file::unbuffered_tell()   // ask server where the offset of the file pointer is
  671. {
  672.   if (socket_fd>=0)
  673.   {
  674.     uchar cmd=NFCMD_TELL;
  675.     if (write(socket_fd,&cmd,sizeof(cmd))!=sizeof(cmd)) { r_close("tell : could not send command"); return 0; }
  676.  
  677.     long offset;
  678.     if (read(socket_fd,&offset,sizeof(offset))!=sizeof(offset)) { r_close("tell : could not read offset"); return 0; }    
  679.     return swap_long(offset);
  680.   }    
  681.   return 0;
  682. }
  683.  
  684. int remote_file::unbuffered_seek(long offset)  // tell server to seek to a spot in a file
  685. {
  686.   if (socket_fd>=0)
  687.   {
  688.     uchar cmd=NFCMD_SEEK;
  689.     if (write(socket_fd,&cmd,sizeof(cmd))!=sizeof(cmd)) { r_close("seek : could not send command"); return 0; }
  690.  
  691.     long off=swap_long(offset);
  692.     if (write(socket_fd,&off,sizeof(off))!=sizeof(off)) { r_close("seek : could not send offset"); return 0; }
  693.  
  694.     if (read(socket_fd,&offset,sizeof(offset))!=sizeof(offset)) { r_close("seek : could not read offset"); return 0; }    
  695.     return swap_long(offset);
  696.   }    
  697.   return 0;
  698. }
  699.  
  700. int open_file(char *&filename, char *mode)
  701. {
  702.   if (filename[0]!='/' && filename[1]!='/' && default_fs_name[0])   // default file server?
  703.   {
  704.     char tmp_fn[500];  
  705.     sprintf(tmp_fn,"//%s/%s",default_fs_name,filename);
  706.     strcpy(filename,tmp_fn);
  707.   }
  708.  
  709.   if (filename[0]=='/' && filename[1]=='/')   // passive server file refrence?
  710.   {
  711.     int use_port=DEFAULT_COMM_PORT;
  712.  
  713.     char server_name[100],*sn;
  714.     filename+=2;
  715.     sn=server_name;
  716.     while (*filename && *filename!='/' && *filename!=':')
  717.       *(sn++)=*(filename++);    
  718.     *sn=0;
  719.  
  720.     if (*filename==':')    // a port is included in the filename
  721.     {
  722.       filename++;
  723.       char port[100],*p; p=port;
  724.       while (*filename && *filename!='/')
  725.       { *(p++)=*(filename++); }
  726.       *p=0;
  727.       if (!sscanf(port,"%d",&use_port) || use_port<0 || use_port>0x7fff) return -1;
  728.     }
  729.  
  730.     filename++;
  731.  
  732.  
  733.     
  734.  
  735.     if (!local_address(server_name))
  736.     {
  737.       remote_file *rf=new remote_file(server_name,use_port,filename,mode,remote_file_list);
  738.       if (rf->open_failure())
  739.       {
  740.         delete rf;
  741.     return -1;
  742.       }
  743.       else 
  744.       {
  745.     remote_file_list=rf;
  746.     return rf->socket_fd;
  747.       }      
  748.     }      
  749.   }
  750.  
  751.   secure_filename(filename,mode);
  752.   if (filename[0]==0) return -1;
  753.  
  754.   int flags=0;
  755.   while (*mode)
  756.   {
  757.     if (*mode=='w') flags|=O_CREAT|O_RDWR;
  758.     else if (*mode=='r') flags|=O_RDONLY;
  759.     mode++;
  760.   }
  761.  
  762.   int f=open(filename,flags,S_IRWXU | S_IRWXG | S_IRWXO);
  763.   if (f>=0)
  764.   { close(f);
  765.     return -2;
  766.   }
  767.   
  768.   return -1;
  769. }
  770.  
  771. remote_file *find_rfile(int fd)
  772. {
  773.   remote_file *r=remote_file_list;
  774.   for (;r && r->socket_fd!=fd;r=r->next)
  775.   {
  776.     if (r->socket_fd==-1)
  777.     {
  778.       fprintf(stderr,"bad sock\n");
  779.     }
  780.   }
  781.   return r;
  782. }
  783.  
  784. void unlink_remote_file(remote_file *rf)
  785. {
  786.   if (rf==remote_file_list)
  787.     remote_file_list=rf->next;
  788.   else
  789.   {
  790.     remote_file *last=remote_file_list;
  791.     while (last->next && last->next!=rf) last=last->next;
  792.     last->next=rf->next;
  793.   }
  794. }
  795.  
  796. void process_engine_command()
  797. {
  798.   uchar cmd;
  799.   if (read(driver_in_fd,&cmd,1)!=1) { mdie("could not read command from engine"); }
  800.   switch (cmd)
  801.   {
  802.     case EGCMD_DIE :
  803.     {
  804.       mdie("received die command");
  805.     } break;
  806.  
  807.     case NFCMD_SET_FS :
  808.     {
  809.       uchar size;
  810.       char sn[256];
  811.       if (read(driver_in_fd,&size,1)!=1) mdie("could not read filename length");
  812.       if (read(driver_in_fd,sn,size)!=size) mdie("could not read server name");
  813.       strcpy(default_fs_name,sn);
  814.       size=1;  // return success
  815.       if (write(driver_out_fd,&size,1)!=1) mdie("could not send ok to engine");
  816.     } break;    
  817.  
  818.     case NFCMD_OPEN :
  819.     {
  820.       uchar size[2];
  821.       char filename[300],mode[20],*fn;
  822.       fn=filename;
  823.       if (read(driver_in_fd,size,2)!=2) mdie("could not read fd on open");
  824.       if (read(driver_in_fd,filename,size[0])!=size[0]) mdie("incomplete filename");
  825.       if (read(driver_in_fd,mode,size[1])!=size[1]) mdie("incomplete mode string");
  826.       
  827.       int fd=open_file(fn,mode);
  828.       if (fd==-2)
  829.       {
  830.     uchar st[2];
  831.     st[0]=NF_OPEN_LOCAL_FILE;
  832.     st[1]=strlen(fn)+1;
  833.     if (write(driver_out_fd,st,2)!=2) comm_failed();
  834.     if (write(driver_out_fd,fn,st[1])!=st[1]) comm_failed();
  835.       } else if (fd==-1)
  836.       {
  837.     uchar st=NF_OPEN_FAILED;
  838.     if (write(driver_out_fd,&st,1)!=1) comm_failed(); 
  839.       } else
  840.       {
  841.     uchar st=NF_OPEN_REMOTE_FILE;
  842.     if (write(driver_out_fd,&st,1)!=1) comm_failed();     
  843.     if (write(driver_out_fd,&fd,sizeof(fd))!=sizeof(fd)) comm_failed();     
  844.       }
  845.  
  846.     } break;
  847.     case NFCMD_CLOSE :
  848.     case NFCMD_SIZE :
  849.     case NFCMD_TELL :
  850.     case NFCMD_SEEK :
  851.     case NFCMD_READ :
  852.     {
  853.       int fd;
  854.       if (read(driver_in_fd,&fd,sizeof(fd))!=sizeof(fd)) comm_failed();
  855.       remote_file *rf=find_rfile(fd);
  856.       if (!rf) 
  857.     mdie("bad fd for engine command");
  858.  
  859.       switch (cmd)
  860.       {
  861.     case NFCMD_CLOSE : 
  862.     { 
  863.       unlink_remote_file(rf);
  864.       delete rf; 
  865.       uchar st=1;
  866.       if (write(driver_out_fd,&st,1)!=1) comm_failed();     
  867.     } break;
  868.     case NFCMD_SIZE  :
  869.     {
  870.       if (write(driver_out_fd,&rf->size,sizeof(rf->size))!=sizeof(rf->size)) comm_failed();           
  871.     } break;
  872.     case NFCMD_TELL :
  873.     {
  874.       long offset=rf->unbuffered_tell();
  875.       if (write(driver_out_fd,&offset,sizeof(offset))!=sizeof(offset)) comm_failed();  
  876.     } break;
  877.     case NFCMD_SEEK :
  878.     {
  879.       long offset;
  880.       if (read(driver_in_fd,&offset,sizeof(offset))!=sizeof(offset)) comm_failed();
  881.       offset=rf->unbuffered_seek(offset);
  882.       if (write(driver_out_fd,&offset,sizeof(offset))!=sizeof(offset)) comm_failed();  
  883.     } break;
  884.     case NFCMD_READ :
  885.     {
  886.       long size;
  887.       if (read(driver_in_fd,&size,sizeof(size))!=sizeof(size)) comm_failed();
  888.       rf->unbuffered_read(driver_out_fd,size);
  889.     } break;
  890.       }
  891.     } break;    
  892.     default :
  893.     { fprintf(stderr,"net driver : unknown net command %d\n",cmd); die(0); }
  894.   } 
  895.   
  896. }
  897.  
  898. int process_nfs_command(nfs_client *c)
  899. {
  900.   char cmd;
  901.   if (read(c->socket_fd,&cmd,1)!=1) return 0;
  902.   switch (cmd)
  903.   {
  904.     case NFCMD_READ :
  905.     {
  906.       long size;
  907.       if (read(c->socket_fd,&size,sizeof(size))!=sizeof(size)) return 0;
  908.       size=swap_long(size);
  909.  
  910.       c->size_to_read=size;
  911.       return c->send_read();
  912.     } break;
  913.     case NFCMD_CLOSE :
  914.     {
  915.       return 0;
  916.     } break;
  917.     case NFCMD_SEEK :
  918.     {
  919.       long offset;
  920.       if (read(c->socket_fd,&offset,sizeof(offset))!=sizeof(offset)) return 0;
  921.       offset=swap_long(offset);
  922.       offset=lseek(c->file_fd,offset,0);
  923.       offset=swap_long(offset);
  924.       if (write(c->socket_fd,&offset,sizeof(offset))!=sizeof(offset)) return 0;
  925.       return 1;
  926.     } break;
  927.     case NFCMD_TELL :
  928.     {
  929.       long offset=lseek(c->file_fd,0,SEEK_CUR);
  930.       offset=swap_long(offset);
  931.       if (write(c->socket_fd,&offset,sizeof(offset))!=sizeof(offset)) return 0;
  932.       return 1;
  933.     } break;
  934.     
  935.     default :
  936.     { fprintf(stderr,"net driver : bad command from nfs client\n");
  937.       return 0;
  938.     }
  939.   } 
  940. }
  941.  
  942. void get_game_data(client *c)
  943. {
  944.   fprintf(stderr,"Get game data from client id %d\n",c->client_id);
  945. }
  946.  
  947.  
  948. void add_nfs_client(int fd)
  949. {
  950.   uchar size[2];
  951.   char filename[300],mode[20],*mp;
  952.   if (read(fd,size,2)!=2) { close(fd); return ; }
  953.   if (read(fd,filename,size[0])!=size[0]) { close(fd); return ; }
  954.   if (read(fd,mode,size[1])!=size[1]) { close(fd); return ; }
  955.  
  956.   fprintf(stderr,"remote request for %s ",filename);
  957.  
  958.   secure_filename(filename,mode);  // make sure this filename isn't a security risk
  959.   if (filename[0]==0) { fprintf(stderr,"(denied)\n"); close(fd); return ; }
  960.  
  961.   mp=mode;
  962.   int flags=0;
  963.  
  964.   while (*mp)
  965.   {
  966.     if (*mp=='w') flags|=O_CREAT|O_RDWR;
  967.     else if (*mp=='r') flags|=O_RDONLY;
  968.     mp++;
  969.   }
  970.       
  971.   int f=open(filename,flags,S_IRWXU | S_IRWXG | S_IRWXO);
  972.   
  973.   if (f<0) 
  974.   {
  975.     fprintf(stderr,"(not found)\n");
  976.     f=-1;  // make sure this is -1
  977.   } else fprintf(stderr,"(granted, fd=%d)\n",f);
  978.  
  979.   long ret=swap_long(f);
  980.   if (write(fd,&ret,sizeof(ret))!=sizeof(ret)) { close(fd); return ; }
  981.  
  982.   if (f<0)    // no file, sorry
  983.     close(fd);
  984.   else
  985.   {
  986.     long cur_pos=lseek(f,0,SEEK_CUR);
  987.     long size=lseek(f,0,SEEK_END);
  988.     lseek(f,cur_pos,SEEK_SET);
  989.     size=swap_long(size);
  990.     if (write(fd,&size,sizeof(size))!=sizeof(size)) {  close(f); close(fd); return ; }
  991.  
  992.     first_nfs_client=new nfs_client(fd,f,first_nfs_client);
  993.     first_nfs_client->size=size;
  994.   }
  995. }
  996.  
  997. int isa_client(int client_id)    // sreach the list of active clients for this id and return 1 if found
  998. {
  999.   int i;
  1000.   client *c=first_client;
  1001.   for (;c;c=c->next)
  1002.     if (c->client_id==client_id) return 1;
  1003.   return 0;  
  1004. }
  1005.  
  1006. void insert_client(int client_id)  // add the client_id into the list of active clients
  1007. {
  1008. //  client_array[client_id]
  1009. //  if (!base->active_clients)
  1010.     
  1011. }
  1012.  
  1013. int add_game_client(int fd)     // returns false if could not join client
  1014. {  
  1015.   fprintf(stderr,"add game client\n");
  1016.  
  1017.   int i,first_free=-1;
  1018.   for (i=0;first_free==-1 && i<MAX_JOINERS;i++)
  1019.     if (join_array[i].client_id==-1)
  1020.       first_free=i;
  1021.  
  1022.   if (first_free==-1) return 0;
  1023.  
  1024.   int first_free_client=-1;
  1025.   for (i=0;first_free_client==-1 && i<MAX_CLIENTS;i++)
  1026.     if (!isa_client(i)) 
  1027.       first_free_client=i;
  1028.  
  1029.   if (first_free_client==-1) return 0;  
  1030.  
  1031.  
  1032.   join_array[first_free].next=base->join_list;
  1033.   base->join_list=&join_array[first_free];      
  1034.   join_array[first_free].client_id=first_free_client; 
  1035.   
  1036.   first_client=new client(fd,first_free_client,first_client);
  1037.  
  1038. }
  1039.  
  1040.  
  1041. void add_client()
  1042. {
  1043.   struct sockaddr from;
  1044.   int addr_len=sizeof(from);
  1045.   int new_fd=accept(comm_fd,&from,&addr_len);
  1046.   if (new_fd>=0)
  1047.   {
  1048.     char client_type;
  1049.     if (read(new_fd,&client_type,1)!=1 ||
  1050.     !(client_type==CLIENT_NFS ||
  1051.     client_type==CLIENT_ABUSE)) { close(new_fd); return ; }
  1052.  
  1053.     if (client_type==CLIENT_NFS)
  1054.       add_nfs_client(new_fd);
  1055.     else add_game_client(new_fd);    
  1056.   }
  1057. }
  1058.  
  1059. void net_watch()
  1060. {
  1061.   int i;
  1062.   client_array=(client_struct *)(base+1);
  1063.   join_array=(join_struct *) (client_array+MAX_CLIENTS);
  1064.  
  1065.   for (i=0;i<MAX_JOINERS;i++)
  1066.     join_array[i].client_id=-1;
  1067.  
  1068.   for (i=0;i<MAX_CLIENTS;i++)
  1069.     client_array[i].client_id=i;
  1070.  
  1071.   fd_set read_set,exception_set,write_set;
  1072.   
  1073.   FD_ZERO(&master_set);  
  1074.   FD_ZERO(&master_write_set);  
  1075.   FD_SET(comm_fd,&master_set);     // new incoming connections & nfs data
  1076.   FD_SET(game_fd,&master_set);     // game data
  1077.  
  1078.   if (!stand_alone)
  1079.   {
  1080.     FD_SET(driver_in_fd,&master_set);  // request from engine
  1081.     FD_SET(driver_out_fd,&master_set); // check for error on messages to engine
  1082.   }
  1083.  
  1084.   while (1)
  1085.   {
  1086.     // first lets set up a select that will cover all of our fd's so if nothing is happening
  1087.     // we can block and take no CPU time.
  1088.  
  1089.     memcpy(&read_set,&master_set,sizeof(master_set));
  1090.     memcpy(&exception_set,&master_set,sizeof(master_set));
  1091.     memcpy(&write_set,&master_write_set,sizeof(master_set));
  1092.     
  1093.  
  1094.     select(FD_SETSIZE,&read_set,&write_set,&exception_set,NULL);
  1095.  
  1096.     if (!stand_alone)
  1097.     {
  1098.       // see if we had any errors talking to the engine
  1099.       if (FD_ISSET(driver_in_fd,&exception_set) ||
  1100.       FD_ISSET(driver_out_fd,&exception_set))
  1101.       comm_failed();
  1102.       
  1103.       // see if the engine has anything to say before getting to anyone else
  1104.       if (FD_ISSET(driver_in_fd,&read_set))
  1105.         process_engine_command();
  1106.     }
  1107.  
  1108.     if (aquire_mem_lock())  // we need to change shared memory, make sure server is not using it.
  1109.     {
  1110.       client *c;
  1111.       for (c=first_client;c;c=c->next)
  1112.       {
  1113.         if (FD_ISSET(c->socket_fd,&exception_set))  // error?
  1114.       delete_client(c);
  1115.     else if (FD_ISSET(c->socket_fd,&read_set))  // in comming game data from client?
  1116.       get_game_data(c);
  1117.       }
  1118.  
  1119.       if (FD_ISSET(comm_fd,&read_set))
  1120.         add_client();
  1121.  
  1122.       nfs_client *nc,*last=NULL;
  1123.       for (nc=first_nfs_client;nc;)      // check for nfs request
  1124.       {
  1125.  
  1126.     int ok=1;
  1127.  
  1128.     if (FD_ISSET(nc->socket_fd,&exception_set))
  1129.     {
  1130.       ok=0;
  1131.       fprintf(stderr,"Killing nfs client, socket went bad\n");
  1132.     } 
  1133.     else if (nc->size_to_read)
  1134.     {
  1135.       if (FD_ISSET(nc->socket_fd,&write_set))
  1136.         ok=nc->send_read();
  1137.     }        
  1138.     else if (FD_ISSET(nc->socket_fd,&read_set))
  1139.       ok=process_nfs_command(nc);    // if we couldn't process the packeted, delete the connection
  1140.         
  1141.     if (ok)
  1142.     {
  1143.       last=nc;
  1144.       nc=nc->next;
  1145.     } else
  1146.     {
  1147.       if (last) last->next=nc->next;
  1148.       else first_nfs_client=nc->next;
  1149.       nfs_client *c=nc;
  1150.       nc=nc->next;
  1151.       delete c;
  1152.     }
  1153.       }
  1154.  
  1155.       base->mem_lock=0;
  1156.     }       
  1157.  
  1158.  
  1159.   }
  1160. }
  1161.  
  1162.  
  1163.  
  1164.